﻿using System;
using System.IO;
using System.Windows.Forms;
using DesignerHelper.Commands;
using DesignerHelper.EventHandlers;
using DesignerHelper.Help;
using DesignerHelper.Main;
using DesignerHelper.Properties;
using SpreadsheetGear;
using SpreadsheetGear.Printing;
using SpreadsheetGear.Windows.Forms;
using WorkbookDesigner.Addons.DefineName;
using WorkbookDesigner.UI;
using System.ComponentModel;

namespace WorkbookDesigner.Main
{
    public class BookFormPresenter : IBookEditor
    {
        public BookFormPresenter(IMainWindow mw, IBookForm form)
        {
            Bf = form;
            MdiParent = mw;
        }
        public IMainWindow MdiParent { get; }

        private IBookForm Bf { get; }
        private WorkbookView ActiveView => Bf.WorkbookView;

        public event EventHandler<BookSetEventArgs> BookIsModified;

        private DefineNameDialog Dndia { get; set; }
        private NewLocateRangeDialog Lrdia { get; set; }

        public void SetActiveBook(IWorkbook workbook)
        {
            Bf.WorkbookView.ActiveWorkbook = workbook;
            //ActiveWorkSheet = ActiveBook.Worksheets[0];
            Bf.GetForm().Text = workbook.FullName;
            Bf.GetForm().Name = "WBF_" + workbook.Name;
        }


        #region File相关方法


        public void FileSaveAs()
        {
            IWorkbook book = Bf.WorkbookView.ActiveWorkbook;
            using (SaveFileDialog savefile = GetSaveFileDialog(book.Name))
            {
                switch (savefile.ShowDialog())
                {
                    case DialogResult.OK:
                        ActiveView.DoWork(() =>
                        {
                            // ReSharper disable once AccessToDisposedClosure
                            book.SaveAs(savefile.FileName, GetFileformat(savefile.FilterIndex));
                            //ps check null?
                        });
                        //OnBookIsModified(new BookSetEventArgs(book, BookSetEventArgs.Type.Refresh));
                        Bf.GetForm().Text = savefile.FileName;
                        MesBox.InfoMessage($"成功保存文件至路径 {'\n'}{savefile.FileName}");
                        break;
                    case DialogResult.Cancel:
                        break;
                    default:
                        break;
                }
            }
        }

        public void Preview(PrintWhat printWhat)
        {
            ActiveView.DoWork(() =>
            {
                ActiveView.PrintPreview(printWhat);
            });
        }

        public void Print(PrintWhat printWhat)
        {
            ActiveView.DoWork(() =>
            {
                ActiveView.Print(printWhat, true);
            });
        }

        public void SaveFile()
        {
            IWorkbook workbook = Bf.WorkbookView.ActiveWorkbook;
            if (workbook.FullName == workbook.Name && workbook.Name.StartsWith("Book"))
                //ps 可能需要改进文件保存逻辑
                FileSaveAs();
            else
            {
                try
                {
                    ActiveView.DoWork(workbook.Save);
                    OnBookIsModified(Bf, new BookSetEventArgs(workbook, BookSetEventArgs.Type.Refresh));
                }
                catch (IOException ioEx)
                {
                    MesBox.ErrorMessage(ioEx);
                }

            }
        }

        private static SaveFileDialog GetSaveFileDialog(string fileName)
        {
            SaveFileDialog savefile = new SaveFileDialog
            {
                Filter = Resources.FileDialogFormatFilter,
                FilterIndex = 2,
                OverwritePrompt = true,
                FileName = fileName,
                CheckPathExists = true,
                ValidateNames = true,
                AutoUpgradeEnabled = true,
            };
            return savefile;
        }

        private FileFormat GetFileformat(int filterIndex)
        {
            switch (filterIndex)
            {
                case 2:
                    return FileFormat.OpenXMLWorkbook;

                case 3:
                    return FileFormat.Excel8;

                case 4:
                    return FileFormat.CSV;

                default:
                    return Bf.ActiveBook.FileFormat;
            }
        }

        #endregion File相关方法



        #region Edit相关方法


        public void ClearRangeSelection(Edit.ClearType type)
        {
            Edit.ClearRangeSelection(Bf, type);
        }

        public void ClearWorksheet()
        {
            Edit.ClearWorksheetRange(Bf, Edit.ClearType.All);
        }


        public void CopySheet()
        {
            ActiveView.ActiveCommandManager.Execute(new CopySheet(ActiveView.ActiveWorksheet, true));
            OnBookIsModified(Bf, new BookSetEventArgs(ActiveView.ActiveWorksheet, BookSetEventArgs.Type.Add));
        }

        public void DeleteActiveWorkSheet()
        {
            ActiveView.DoWork(() => Edit.DeleteActiveWorkSheet(Bf));
            //OnBookIsModified(new BookSetEventArgs(Mw.ActiveBookForm.ActiveWorkSheet, BookSetEventArgs.Type.Remove));
        }

        public void EditCopy()
        {
            Edit.CopyRange(Bf);
        }

        public void EditCut()
        {
            Edit.CutRange(Bf);
        }

        public void EditPaste()
        {
            Edit.PasteRange(Bf);
        }

        public void FillRange(Edit.FillType type)
        {
            ActiveView.DoWork(() => Edit.FillRange(Bf, type));
        }

        public void ReDo()
        {
            Edit.ReDo(Bf);
        }

        public void UnDo()
        {
            Edit.UnDo(Bf);
        }

        #endregion

        #region Insert相关方法

        public void InsertOrDeletePageBreaks()
        {
            IWorksheet sheet = ActiveView.ActiveWorksheet;
            IVPageBreaks vb = sheet.VPageBreaks;
            IHPageBreaks hb = sheet.HPageBreaks;
            ActiveView.DoWork(() =>
            {
                if (vb.Count != 0 && hb.Count != 0)
                {
                    for (int i = 0; i < vb.Count; i++)
                    {
                        vb[i].Delete();
                        hb[i].Delete();
                        i--;
                    }
                }
                else
                {
                    IRange r = ActiveView.RangeSelection;
                    if (r.Row == 0 || r.Column == 0)
                        return;
                    vb.Add(ActiveView.RangeSelection);
                    hb.Add(ActiveView.RangeSelection);
                }
            });
        }

        public void InsertWorkSheets()
        {
            try
            {
                ActiveView.DoWork(() =>
                {
                    IWorksheet newWorksheet = Bf.ActiveBook.Worksheets.Add();
                    OnBookIsModified(Bf, new BookSetEventArgs(newWorksheet, BookSetEventArgs.Type.Add));
                });
            }
            finally
            {

            }
        }


        #endregion

        public void ShowDefineNameDialog()
        {
            if (Dndia != null)
                Dndia.Activate();
            else
            {
                Dndia = new DefineNameDialog(Bf.WorkbookView);
                Dndia.Show(Bf.GetForm());
                Dndia.FormClosed += (x, y) => { Dndia = null; };
            }
        }

        public void ShowLocateRangeDialog()
        {
            if (Lrdia != null)
                Lrdia.Activate();
            else
            {
                Lrdia = new NewLocateRangeDialog(Bf.WorkbookView);
                Lrdia.Show(Bf.GetForm());
                Lrdia.FormClosed += (x, y) => { Lrdia = null; };
            }
        }
        public void DefineNamesFromSelection()
        {
            using (DefineFromSelectionDialog dialog = new DefineFromSelectionDialog(Bf.WorkbookView.RangeSelection))
            {
                dialog.ShowDialog(Bf.GetForm());
            }
        }

        public void HightLightTheCell(CellEndEditEventArgs e)
        {
            HighLight(e.ActiveCell[0, 0], e.Entry.StartsWith("="));
            //e.ActiveCell[0, 0].Font.Color = e.Entry.StartsWith("=") ? Colors.Red : Colors.Black;
        }

        private static void HighLight(IRange range, bool hasFormula)
        {
            range.Font.Color = hasFormula ? Colors.Red : Colors.Black;
        }

        public void OpenDeleteCellsDialog()
        {
            DeleteCellsDialog.ShowStaticDialog(Bf.ParentForm);
        }

        public void OpenInsertCellsDialog()
        {
            InsertCellsDialog.ShowStaticDialog(Bf.ParentForm);
        }

        public void OpenPasteSpecialDialog()
        {
            PasteSpecialDialog.ShowForm(Bf.ParentForm);
        }

        public void FormClosed(object sender, FormClosedEventArgs e)
        {
            Lrdia?.Close();
            Dndia?.Close();
            MdiParent.FileOperator.Close(Bf);
        }

        public void FormClosing(object sender, FormClosingEventArgs e)
        {
            IWorkbook workbook = Bf.WorkbookView.ActiveWorkbook;
            if (!workbook.IsModified)
                return;
            switch (MesBoxWhenClosing())
            {
                case DialogResult.Yes:
                    Bf.SaveFile();
                    if (workbook.IsModified)
                    {
                        e.Cancel = true;
                    }
                    break;

                case DialogResult.No:
                    e.Cancel = false;
                    break;
                case DialogResult.Cancel:
                    e.Cancel = true;
                    return;
            }
        }

        public void FormLoad()
        {
            //LbwTrigger.DoWork(() =>
            //{
            //    foreach (IWorksheet sheet in ActiveBook.Worksheets)
            //    {
            //        IRange usedRange = sheet.UsedRange;
            //        //sheet.Names.Add("UsedRange" + sheet.Name, "=" + usedRange.GetAddress(true, true, ReferenceStyle.A1, true, null));
            //        foreach (IRange cell in usedRange.Cells.Cast<IRange>().Where(cell => cell.HasFormula))
            //        {
            //            //HightLight(cell, cell.HasFormula);
            //        }
            //    }
            //});

        }

        public void ContextMenuStripOpening(CancelEventArgs e, ToolStripMenuItem aboutComment, ToolStripMenuItem showComments, ToolStripMenuItem deleteComments, ToolStripMenuItem editComments)
        {
            WorkbookView wbv = Bf.WorkbookView;
            wbv.DoWork(() =>
            {
                IRange rangeSelection = wbv.RangeSelection;
                if (rangeSelection.CellCount > 1)
                {
                    aboutComment.Enabled = false;
                    return;
                }
                aboutComment.Enabled = true;
                showComments.Enabled = true;
                var comment = rangeSelection.Comment;//Main?
                deleteComments.Enabled
                    = editComments.Enabled
                        = showComments.Enabled = comment != null;
                if (comment == null)
                    return;

                showComments.Text = comment.Visible ? "隐藏批注" : "显示批注";

            });

        }

        private DialogResult MesBoxWhenClosing()
        {
            return MessageBox.Show($"{Bf.GetForm().Text} 已经修改，是否保存？", About.MyName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
        }


        private void OnBookIsModified(object sender, BookSetEventArgs e)
        {
            BookIsModified?.Invoke(sender, e);
        }
    }


}
